/*
 * Copyright 2009 Eat Local Food, LLC
 * Copyright (c) 2007 osCommerce (this file was written after
 * code review of osCommerce).
 *
 * This file is part of gwtCommerce.
 *
 * gwtCommerce is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 2 of the License, or
 * (at your option) any later version.
 *
 * gwtCommerce is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with gwtCommerce.  If not, see <http://www.gnu.org/licenses/>.
 */
package com.elf.gwt.store.client.subcomponents;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Set;

import com.elf.gwt.common.client.access.RequestParameter;
import com.elf.gwt.common.client.callback.SubComponentCallback;
import com.elf.gwt.common.client.model.CheckoutModel;
import com.elf.gwt.common.client.model.PaymentModel;
import com.elf.gwt.common.client.utils.CommonUtils;
import com.elf.gwt.store.client.GWTCommerceConstants;
import com.elf.gwt.store.client.GWTCommerceModuleConstants;
import com.elf.gwt.store.client.StoreComponentController;
import com.elf.gwt.store.client.components.CheckoutComponent;
import com.google.gwt.core.client.GWT;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.DialogBox;
import com.google.gwt.user.client.ui.FlowPanel;
import com.google.gwt.user.client.ui.FormPanel;
import com.google.gwt.user.client.ui.Grid;
import com.google.gwt.user.client.ui.HasHorizontalAlignment;
import com.google.gwt.user.client.ui.HasVerticalAlignment;
import com.google.gwt.user.client.ui.Hidden;
import com.google.gwt.user.client.ui.HorizontalPanel;
import com.google.gwt.user.client.ui.Image;
import com.google.gwt.user.client.ui.InlineHTML;
import com.google.gwt.user.client.ui.InlineLabel;
import com.google.gwt.user.client.ui.ListBox;
import com.google.gwt.user.client.ui.RadioButton;
import com.google.gwt.user.client.ui.TextBox;
import com.google.gwt.user.client.ui.VerticalPanel;

/**
 *  Subcomponent for payment modules
 */
public class CheckoutPaymentSubComponent extends CheckoutSubComponent
{
	protected InlineHTML warningLabel;
	public HashMap<String, PaymentPanel> modulePaymentPanelHash;
	protected boolean checkoutCompleted;

	/**
	 * Constructor
	 */
	public CheckoutPaymentSubComponent(
			StoreComponentController controller, 
			SubComponentCallback callback)
	{
		super(controller, null, callback);
		modulePaymentPanelHash = new HashMap<String, PaymentPanel>();
	}

	/**
	 * build
	 */
	public void build() 
	{
		CheckoutModel checkoutModel = checkoutComponent.getCheckoutModel();
		
		GWTCommerceModuleConstants moduleConstants = controller.getStoreModuleConstants();

		String selectedPaymentModule = checkoutModel.getSelectedPaymentModule();
		if (selectedPaymentModule == null)selectedPaymentModule = "";

		List<PaymentModel> payments = checkoutModel.getPayments();
		thisComponent.clear();
		int i = 0;
		for (Iterator<PaymentModel> iter = payments.iterator(); iter.hasNext(); )
		{
			PaymentModel payment = iter.next();
			String paymentModule = payment.getModule();
			if (selectedPaymentModule.length() == 0 && i == 0) checkoutModel.setSelectedPaymentModule(paymentModule);

			try {
				paymentModule = moduleConstants.getString("Payment_" + paymentModule);
			} catch (Exception e){}

			Grid grid = new Grid(1, 3);
			RadioButton selectButton = new RadioButton("payment_service");
			selectButton.setTitle(payment.getModule());
			selectButton.addClickHandler(
					new ClickHandler() {
						public void onClick(ClickEvent event) {
							CheckoutModel checkoutModel = checkoutComponent.getCheckoutModel();
							RadioButton button = (RadioButton)event.getSource();
							if (button.getValue())
							{
								String module = button.getTitle();
								checkoutModel.setSelectedPaymentModule(module);
							}
						}});

			selectButton.setVisible(!checkoutCompleted);

			if (selectedPaymentModule.length() > 0)
			{
				if (selectedPaymentModule.equals(payment.getModule())) selectButton.setValue(true);
			}
			else if (i == 0) selectButton.setValue(true);

			grid.setWidget(0, 0, selectButton);
			grid.setText(0,	1, paymentModule);
			String[] ccs = payment.getAcceptedCreditCards();
			if (ccs != null && ccs.length > 0)
			{
				HorizontalPanel hpanel = new HorizontalPanel();
				hpanel.setVisible(!checkoutCompleted);
				for (int j=0; j< ccs.length; j++)
				{
					if (ccs[j].length() > 0)
					{
						String imageName = "";
						try {
							imageName = moduleConstants.getString("Payment_" + ccs[j].toLowerCase() + "_icon").trim();
						}
						catch (Exception e){};
						if (imageName.length() > 0)
						{
							Image image = new Image(getImageDirectory() + imageName);
							hpanel.add(image);
							hpanel.setCellVerticalAlignment(image, HasVerticalAlignment.ALIGN_BOTTOM);
						}
						else
						{
							InlineLabel label = new InlineLabel(ccs[j]);
							hpanel.add(label);
						}
					}
				}
				grid.setWidget(0, 2, hpanel);
			}

			thisComponent.add(grid);
			PaymentPanel ccPanel = null;
			GWT.log("payment method = " + payment.getMethod());
			GWT.log("third party payment process = " + payment.getThirdPartyPaymentProcess());
			GWT.log("pass cc = " + payment.getPassCC());
			if (payment.getMethod().equals("credit") && payment.getThirdPartyPaymentProcess() && payment.getPassCC())
			{
				ccPanel = modulePaymentPanelHash.get(payment.getModule());
				if (ccPanel == null) {
					ccPanel = new CreditCardThirdPartyPaymentProcessPanelPassCC();
					modulePaymentPanelHash.put(payment.getModule(), ccPanel);
				}
			}
			else if (payment.getMethod().equals("credit") && payment.getThirdPartyPaymentProcess() && !payment.getPassCC())
			{
				ccPanel = modulePaymentPanelHash.get(payment.getModule());
				if (ccPanel == null) {
					ccPanel = new CreditCardThirdPartyAuthorizationPanel();
					modulePaymentPanelHash.put(payment.getModule(), ccPanel);
				}
			}
			else if (payment.getMethod().equals("credit") && !payment.getThirdPartyPaymentProcess())
			{
				ccPanel = modulePaymentPanelHash.get(payment.getModule());
				if (ccPanel == null) {
					ccPanel = new CreditCardPanel();
					modulePaymentPanelHash.put(payment.getModule(), ccPanel);
				}
				ccPanel.setCheckoutCompleted(checkoutCompleted);
				ccPanel.build();
				thisComponent.add(ccPanel);
			}
			if (ccPanel != null) {
				ccPanel.setPaymentModel(payment);
				ccPanel.setCheckoutCompleted(checkoutCompleted);
				ccPanel.build();
				thisComponent.add(ccPanel);
			}
			thisComponent.add(new InlineHTML("<br/>"));
			i++;
		}
		if (checkoutCompleted) modulePaymentPanelHash.clear();
	}

	public boolean isAjaxCheckout() {
		CheckoutModel checkoutModel = checkoutComponent.getCheckoutModel();
		String selectedPaymentModule = checkoutModel.getSelectedPaymentModule();
		PaymentPanel paymentPanel = modulePaymentPanelHash.get(selectedPaymentModule);
		if (paymentPanel != null) {
			return paymentPanel.isAjaxCheckout();
		}
		return true;
	}

	public void submit(List<RequestParameter> parameters) {
		CheckoutModel checkoutModel = checkoutComponent.getCheckoutModel();
		String selectedPaymentModule = checkoutModel.getSelectedPaymentModule();
		PaymentPanel paymentPanel = modulePaymentPanelHash.get(selectedPaymentModule);
		if (paymentPanel != null && !paymentPanel.isAjaxCheckout()) {
			paymentPanel.submit(parameters);
		}
	}

	public List<RequestParameter> getAdditionalRequestParameters()
	{
		CheckoutModel checkoutModel = checkoutComponent.getCheckoutModel();
		
		List<RequestParameter> requestParameters = null;
		String selectedPaymentModule = checkoutModel.getSelectedPaymentModule();
		PaymentPanel paymentPanel = modulePaymentPanelHash.get(selectedPaymentModule);
		if (paymentPanel != null) {
			requestParameters = paymentPanel.getAdditionalRequestParameters();
		}
		else {
			requestParameters = new ArrayList<RequestParameter>();
		}

		return requestParameters;
	}

	public String validate(String action)
	{
		CheckoutModel checkoutModel = checkoutComponent.getCheckoutModel();
		
		String warningText = "";
		String selectedPaymentModule = checkoutModel.getSelectedPaymentModule();
		PaymentPanel paymentPanel = modulePaymentPanelHash.get(selectedPaymentModule);
		if (paymentPanel != null) {
			warningText += paymentPanel.validate(action);
		}
		return warningText;
	}

	public class PaymentPanel extends FlowPanel
	{
		protected PaymentModel paymentModel;
		protected boolean checkoutCompleted;

		public PaymentPanel()
		{
		}

		public void setPaymentModel(PaymentModel payment)
		{
			this.paymentModel = payment;
		}
		
		public void build()
		{

		}

		public boolean isAjaxCheckout() {
			return true;
		}
		
		public void submit(List<RequestParameter> requestParameters) {
			
		}
		
		public List<RequestParameter> getAdditionalRequestParameters()
		{
			List<RequestParameter> requestParameters = new ArrayList<RequestParameter>();
			requestParameters.add(new RequestParameter("paymentMethod", paymentModel.getMethod()));
			return requestParameters;
		}

		public String validate(String action)
		{
			return "";
		}

		public void setCheckoutCompleted(boolean checkoutCompleted) {
			this.checkoutCompleted = checkoutCompleted;
		}
	}

	public class CreditCardPanel extends PaymentPanel
	{
		protected ListBox creditCardTypeListBox;
		protected TextBox creditCardNumberTextBox;
		protected ListBox creditCardExpirationMonthListBox;
		protected ListBox creditCardExpirationYearListBox;
		protected TextBox creditCardCVVTextBox;
		protected DialogBox dialogBox;

		protected Grid paymentGrid;
		protected Grid payedGrid;

		public CreditCardPanel()
		{
			super();
		}

		public void build()
		{
			if (creditCardTypeListBox == null)
			{
				int gridrow = 0;
				creditCardTypeListBox = new ListBox();

				String[] ccs = paymentModel.getAcceptedCreditCards();
				if (ccs != null && ccs.length > 0)
				{
					for (int j=0; j< ccs.length; j++)
					{
						if (ccs[j].length() > 0)
						{
							creditCardTypeListBox.addItem(ccs[j]);
						}
					}
					creditCardTypeListBox.setSelectedIndex(0);
				}
				gridrow++;

				creditCardNumberTextBox = new TextBox();
				gridrow++;

				creditCardExpirationMonthListBox = new ListBox();
				creditCardExpirationMonthListBox.addItem("01", "01");
				creditCardExpirationMonthListBox.addItem("02", "02");
				creditCardExpirationMonthListBox.addItem("03", "03");
				creditCardExpirationMonthListBox.addItem("04", "04");
				creditCardExpirationMonthListBox.addItem("05", "05");
				creditCardExpirationMonthListBox.addItem("06", "06");
				creditCardExpirationMonthListBox.addItem("07", "07");
				creditCardExpirationMonthListBox.addItem("08", "08");
				creditCardExpirationMonthListBox.addItem("09", "09");
				creditCardExpirationMonthListBox.addItem("10", "10");
				creditCardExpirationMonthListBox.addItem("11", "11");
				creditCardExpirationMonthListBox.addItem("12", "12");
				creditCardExpirationMonthListBox.setSelectedIndex(0);
				creditCardExpirationYearListBox = new ListBox();
				int ccYear = Integer.parseInt(CommonUtils.yearFormat.format(new Date()));
				creditCardExpirationYearListBox.addItem(String.valueOf(ccYear), String.valueOf(ccYear));
				ccYear++;
				creditCardExpirationYearListBox.addItem(String.valueOf(ccYear), String.valueOf(ccYear));
				ccYear++;
				creditCardExpirationYearListBox.addItem(String.valueOf(ccYear), String.valueOf(ccYear));
				ccYear++;
				creditCardExpirationYearListBox.addItem(String.valueOf(ccYear), String.valueOf(ccYear));
				ccYear++;
				creditCardExpirationYearListBox.addItem(String.valueOf(ccYear), String.valueOf(ccYear));
				ccYear++;
				creditCardExpirationYearListBox.addItem(String.valueOf(ccYear), String.valueOf(ccYear));
				ccYear++;
				creditCardExpirationYearListBox.addItem(String.valueOf(ccYear), String.valueOf(ccYear));
				ccYear++;
				creditCardExpirationYearListBox.addItem(String.valueOf(ccYear), String.valueOf(ccYear));
				ccYear++;
				creditCardExpirationYearListBox.addItem(String.valueOf(ccYear), String.valueOf(ccYear));
				ccYear++;
				creditCardExpirationYearListBox.setSelectedIndex(0);

				HorizontalPanel creditCardExpirationPanel = new HorizontalPanel();
				creditCardExpirationPanel.add(creditCardExpirationMonthListBox);
				creditCardExpirationPanel.add(creditCardExpirationYearListBox);
				gridrow++;

				if (paymentModel.isCheckCVV())
				{
					creditCardCVVTextBox = new TextBox();
					creditCardCVVTextBox.setMaxLength(5);
					creditCardCVVTextBox.setWidth("50");
					gridrow++;
				}

				paymentGrid = new Grid(gridrow,3);

				gridrow = 0;
				paymentGrid.setStyleName(handle + "SubPanel");
				paymentGrid.getColumnFormatter().setStyleName(0, handle + "SubPanelCol0");
				this.add(paymentGrid);

				GWTCommerceConstants constants = getController().getStoreConstants();
				
				CommonUtils.addGridWidget(handle, gridrow, creditCardTypeListBox, paymentGrid, "creditCardType", 
						constants.CheckoutComponentCreditCardType(), "*");
				gridrow++;

				CommonUtils.addGridWidget(handle, gridrow, creditCardNumberTextBox, paymentGrid, "creditCardNumber", 
						constants.CheckoutComponentCreditCardNumber(), "*");
				gridrow++;

				CommonUtils.addGridWidget(handle, gridrow, creditCardExpirationPanel, paymentGrid, "creditCardExpiration", 
						constants.CheckoutComponentCreditCardExpiration(), "*");
				gridrow++;

				if (paymentModel.isCheckCVV())
				{
					CommonUtils.addGridWidget(handle, gridrow, creditCardCVVTextBox, paymentGrid, "creditCardCVV", 
							"", "*");
					FlowPanel flowPanel = new FlowPanel();
					InlineHTML ccvLabel = new InlineHTML(constants.CheckoutComponentCreditCardValidation());
					flowPanel.add(ccvLabel);
					InlineHTML ccvWhatIsIt = new InlineHTML(" " + constants.CheckoutComponentCVVWhatIsIt());
					ccvWhatIsIt.setStyleName("ComponentLink");
					ccvWhatIsIt.addClickHandler(new ClickHandler() {
						public void onClick(ClickEvent event) {
							DialogBox dialogBox = getCVVImageDialogBox();
							dialogBox.center();
							dialogBox.show();
						}
						});
					flowPanel.add(ccvWhatIsIt);
					paymentGrid.setWidget(gridrow, 0, flowPanel);
					gridrow++;
				}

				payedGrid = new Grid(1,3);
				payedGrid.setStyleName(handle + "SubPanel");
				payedGrid.getColumnFormatter().setStyleName(0, handle + "SubPanelCol0");
				payedGrid.getCellFormatter().setWidth(0, 2, "100%");
				this.add(payedGrid);
			}
			String cctext = creditCardNumberTextBox.getValue();
			paymentGrid.setVisible(!checkoutCompleted);
			payedGrid.setVisible(checkoutCompleted && cctext != null && cctext.length() > 0);

			payedGrid.setText(0, 1, creditCardTypeListBox.getValue(creditCardTypeListBox.getSelectedIndex()));
			String cc = "";
			int ln = creditCardNumberTextBox.getValue().length();
			if (ln > 4)
			{
				cc = "************" + cctext.substring(ln-4);
				cctext = "";
			}
			if (checkoutCompleted) creditCardNumberTextBox.setValue("");

			payedGrid.setText(0, 2, cc);
		}

		public List<RequestParameter> getAdditionalRequestParameters()
		{
			List<RequestParameter> requestParameters = super.getAdditionalRequestParameters();
			requestParameters.add(new RequestParameter("creditCardType", creditCardTypeListBox.getValue(creditCardTypeListBox.getSelectedIndex())));
			requestParameters.add(new RequestParameter("creditCardNumber", creditCardNumberTextBox.getValue()));
			requestParameters.add(new RequestParameter("creditCardExpirationMonth", creditCardExpirationMonthListBox.getValue(creditCardExpirationMonthListBox.getSelectedIndex())));
			requestParameters.add(new RequestParameter("creditCardExpirationYear", creditCardExpirationYearListBox.getValue(creditCardExpirationYearListBox.getSelectedIndex())));
			if (paymentModel.isCheckCVV())
			{
				requestParameters.add(new RequestParameter("creditCardCVV", creditCardCVVTextBox.getValue()));
			}
			return requestParameters;
		}

		public String validate(String action)
		{
			String warningText = "";
			if (action != null && action.equals(CheckoutComponent.ProcessPayment))
			{
				int intValid = validateCreditCard(creditCardTypeListBox.getValue(creditCardTypeListBox.getSelectedIndex()),
						creditCardNumberTextBox.getValue(),
						creditCardExpirationMonthListBox.getValue(creditCardExpirationMonthListBox.getSelectedIndex()),
						creditCardExpirationYearListBox.getValue(creditCardExpirationYearListBox.getSelectedIndex()),
						paymentModel.isCheckCVV(),
						creditCardCVVTextBox.getValue());
				GWTCommerceConstants constants = getController().getStoreConstants();
				switch (intValid)
				{
				case 0: break;
				case -1: warningText = constants.CheckoutComponentCreditCardTypeUnknown() + "<br/>"; break;
				case -2: warningText = constants.CheckoutComponentCreditCardTypeNotMatch() + "<br/>"; break;
				case -3: warningText = constants.CheckoutComponentCreditCardExpEntry() + "<br/>"; break;
				case -4: warningText = constants.CheckoutComponentCreditCardCCVInvalidLength() + "<br/>"; break;
				case -5: warningText = constants.CheckoutComponentCreditCardInvalidEntry() + "<br/>"; break;
				default: break;
				}
			}
			return warningText;
		}

		protected DialogBox getCVVImageDialogBox() {
			dialogBox = new DialogBox();

			VerticalPanel dialogContents = new VerticalPanel();
			dialogContents.setSpacing(4);
			dialogBox.setWidget(dialogContents);
			
			Image image = new Image(getImageDirectory() + "cvv.jpg");
			dialogContents.add(image);

			// Add a close button at the bottom of the dialog
			Button closeButton = new Button(getController().getCommonConstants().Close(),
					new ClickHandler() {
				public void onClick(ClickEvent event) {
					dialogBox.hide();
				}
			});
			dialogContents.add(closeButton);
			dialogContents.setCellHorizontalAlignment(closeButton,
					HasHorizontalAlignment.ALIGN_LEFT);
			dialogBox.setStyleName(getHandle() + "DialogBox");
			
			return dialogBox;
		}

	}
	
	public class CreditCardThirdPartyPaymentProcessPanelPassCC extends CreditCardPanel
	{
		FormPanel formPanel = null;
		public CreditCardThirdPartyPaymentProcessPanelPassCC()
		{
			super();
		}

		public boolean isAjaxCheckout() {
			return false;
		}
		
		public List<RequestParameter> getAdditionalRequestParameters()
		{
			List<RequestParameter> requestParameters = new ArrayList<RequestParameter>();
			requestParameters.add(new RequestParameter("paymentMethod", paymentModel.getMethod()));
			return requestParameters;
		}
		
		public void submit(List<RequestParameter> requestParameterList) {
			if (formPanel != null) remove(formPanel);
			HashMap<String, String> partyParameters = paymentModel.getThirdPartyPaymentParameters();
			
			formPanel = new FormPanel("");
			formPanel.setStyleName("CreditCardThirdPartyAuthorizationPanel");
			formPanel.setMethod(FormPanel.METHOD_POST);
			formPanel.setAction(partyParameters.get("action_url"));
			
			FlowPanel flowPanel = new FlowPanel();
			
			String billToName = "";
			String shipToName = "";

			Iterator<RequestParameter> iter = requestParameterList.iterator();
			while (iter.hasNext())
			{
				RequestParameter rp = iter.next();
				String key = rp.getKey();
				String param = rp.getRawValue();
				flowPanel.add(new Hidden("gwt_" + key, param));
				if (key.equals("billToName")) billToName = param;
				if (key.equals("shipToName")) shipToName = param;
			}
			
			Set<String> keys = partyParameters.keySet();
			Iterator<String> iter1 = keys.iterator();
			while (iter1.hasNext()) {
				String key = iter1.next();
				String param = partyParameters.get(key);
				if (key.equals("action_url")) continue;
				if (param.equals("TOKEN_BILLTONAME"))
				{
					param = billToName;
				}
				else if (param.equals("TOKEN_SHIPTONAME"))
				{
					param = shipToName;
				}
				else if (param.equals("TOKEN_CREDITCARDTYPE"))
				{
					param = creditCardTypeListBox.getValue(creditCardTypeListBox.getSelectedIndex());
				}
				else if (param.equals("TOKEN_CREDITCARDNUMBER"))
				{
					param = creditCardNumberTextBox.getValue();
				}
				else if (param.equals("TOKEN_CREDITCARDEXPIRATIONMONTH"))
				{
					param = creditCardExpirationMonthListBox.getValue(creditCardExpirationMonthListBox.getSelectedIndex());
				}
				else if (param.equals("TOKEN_CREDITCARDEXPIRATIONYEAR"))
				{
					param = creditCardExpirationYearListBox.getValue(creditCardExpirationYearListBox.getSelectedIndex());
				}
				else if (param.equals("TOKEN_CREDITCARDEXPIRATIONMONTHSLASHYEAR"))
				{
					String year = creditCardExpirationYearListBox.getValue(creditCardExpirationYearListBox.getSelectedIndex());
					year = year.substring(2);
					param = 
						creditCardExpirationMonthListBox.getValue(creditCardExpirationMonthListBox.getSelectedIndex()) +
						"/" + year;
						
				}
				else if (param.equals("TOKEN_CREDITCARDCVV"))
				{
					param = creditCardCVVTextBox.getValue();
				}

				flowPanel.add(new Hidden(key, param));
			}
			GWT.log(flowPanel.toString());
			formPanel.add(flowPanel);
			add(formPanel);
			formPanel.submit();
		}	
	}
	
	public class CreditCardThirdPartyAuthorizationPanel extends PaymentPanel
	{
		FormPanel formPanel = null;
		public CreditCardThirdPartyAuthorizationPanel()
		{
			super();
			setStyleName("CreditCardThirdPartyAuthorizationPanel");
		}

		public boolean isAjaxCheckout() {
			return false;
		}
		
		public void submit(List<RequestParameter> requestParameterList) {
			clear();
			HashMap<String, String> partyParameters = paymentModel.getThirdPartyPaymentParameters();
			
			formPanel = new FormPanel("");
			formPanel.setMethod(FormPanel.METHOD_POST);
			formPanel.setAction(partyParameters.get("action_url"));
			
			FlowPanel flowPanel = new FlowPanel();
			
			String billToName = "";
			String shipToName = "";

			Iterator<RequestParameter> iter = requestParameterList.iterator();
			while (iter.hasNext())
			{
				RequestParameter rp = iter.next();
				String key = rp.getKey();
				String param = rp.getRawValue();
				flowPanel.add(new Hidden("gwt_" + key, param));
				if (key.equals("billToName")) billToName = param;
				if (key.equals("shipToName")) shipToName = param;
			}
			
			Set<String> keys = partyParameters.keySet();
			Iterator<String> iter1 = keys.iterator();
			while (iter1.hasNext()) {
				String key = iter1.next();
				String param = partyParameters.get(key);
				if (key.equals("action_url")) continue;
				if (param.equals("TOKEN_BILLTONAME"))
				{
					param = billToName;
				}
				else if (param.equals("TOKEN_SHIPTONAME"))
				{
					param = shipToName;
				}
				
				flowPanel.add(new Hidden(key, param));
			}
			
			flowPanel.add(new Hidden("card-type", "VISA"));
			flowPanel.add(new Hidden("card-number", "4111111111111111"));
			flowPanel.add(new Hidden("month-exp", "01"));
			flowPanel.add(new Hidden("year-exp", "2011"));
			GWT.log(flowPanel.toString());
			formPanel.add(flowPanel);
			add(formPanel);
			formPanel.submit();
		}

		public void build()
		{
			
		}
		
	}

	public static int validateCreditCard(String ccType, String ccNumber, String expMonth, String expYear, boolean validateCVV, String cvv)
	{
		//Get Card Number from input
		String cardNumber = ccNumber.replaceAll("[^0-9]", "");

		//Calculate Card Type
		String cardType = "";
		if (cardNumber.matches("^4[0-9]{12}([0-9]{3})?$"))
			cardType = "Visa";
		else if (cardNumber.matches("^5[1-5][0-9]{14}$"))
			cardType = "Mastercard";
		else if (cardNumber.matches("^3[47][0-9]{13}$"))
			cardType = "American Express";
		else if (cardNumber.matches("^3(0[0-5]|[68][0-9])[0-9]{11}$"))
			cardType = "Diners Club";
		else if (cardNumber.matches("^6011[0-9]{12}$"))
			cardType = "Discover";
		else if (cardNumber.matches("^(3[0-9]{4}|2131|1800)[0-9]{11}$"))
			cardType = "JCB";
		else if (cardNumber.matches("^5610[0-9]{12}$"))
			cardType = "Australian BankCard";
		else 
			return -1;

		//Confirm Card Type
		if (!ccType.equals(cardType))
			return -2;

		//Confirm that card is not expired.
		int intNow = Integer.parseInt(CommonUtils.yearMonthFormat.format(new Date()));
		int intExp = Integer.parseInt(expYear + expMonth);
		if (intExp < intNow)
			return -3;

		//Validate CVV
		if (validateCVV)
		{
			int len = cvv.length();
			int validLen = 0;
			boolean check = false;
			if (cardType.equals("American Express")) {
				validLen = 4;
				check = true;
			}
			else if (cardType.equals("Discover")) {
				validLen = 3;
				check = true;
			}
			else if (cardType.equals("Mastercard")) {
				validLen = 3;
				check = true;
			}
			else if (cardType.equals("Visa")) {
				validLen = 3;
				check = true;
			}

			if (check)
			{
				if (len != validLen)
					return -4;
			}
		}

		//Validate number:
		int numSum = 0;
		int len = cardNumber.length();
		int place = 0;
		for (int i=len-1; i>-1; i--)
		{
			int currentNum = Integer.parseInt(cardNumber.substring(i, i+1));
			// Double every second digit
			if (place % 2 == 1) {
				currentNum = 2 * currentNum;
			}
			// Add digits of 2-digit numbers together
			if (currentNum > 9) {
				int firstNum = currentNum % 10;
				int secondNum = (currentNum - firstNum) / 10;
				currentNum = firstNum + secondNum;
			}
			numSum += currentNum;
			place++;
		}
		// If the total has no remainder it's OK
		if (numSum % 10 != 0) return -5;

		return 0;
	}

	public boolean isCheckoutCompleted() {
		return checkoutCompleted;
	}

	public void setCheckoutCompleted(boolean checkoutComplete) {
		this.checkoutCompleted = checkoutComplete;
	}
}
